package eerbaar.shared.internal.tree;

import java.util.ArrayList;
import java.util.List;

import eerbaar.shared.tree.IAttributes;
import eerbaar.shared.tree.INode;
import eerbaar.shared.tree.INodeListener;
import eerbaar.shared.tree.IPayload;

public abstract class AbstractNode implements INode {

    private final IAttributes attributes;

    private final List<INode> list;

    private final List<INodeListener> listeners;

    private final IPayload payload;

    public AbstractNode(IPayload payload) {
        this.payload = payload;
        this.attributes = new AttributesImpl();
        this.list = new ArrayList<INode>();
        this.listeners = new ArrayList<INodeListener>();
    }

    public AbstractNode(IPayload payload, IAttributes attributes) {
        this.payload = payload;
        this.attributes = attributes;
        this.list = new ArrayList<INode>();
        this.listeners = new ArrayList<INodeListener>();
    }

    @Override
    public void add(INode node) {
        this.list.add(node);
        fireChildrenHaveChanged();
    }

    @Override
    public void addListener(INodeListener listener) {

        if (!this.listeners.contains(listener)) {
            this.listeners.add(listener);
        }
    }

    public void addQuiet(INode node) {
        this.list.add(node);
    }

    private void fireChildrenHaveChanged() {
        for (INodeListener l : this.listeners) {
            l.afterChildrenHaveChanged(this);
        }
    }

    @Override
    public IAttributes getAttributes() {
        return this.attributes;
    }

    @Override
    public INode getChild(int index) {
        return this.list.get(index);
    }

    @Override
    public int getChildCount() {
        return this.list.size();
    }

    @Override
    public INode[] getChildren() {
        return this.list.toArray(new INode[] {});
    }

    @Override
    public IPayload getPayload() {
        return this.payload;
    }

    @Override
    public void remove(INode node) {
        this.list.remove(node);
        fireChildrenHaveChanged();
    }

    @Override
    public void removeListener(INodeListener listener) {
        if (this.listeners.contains(listener)) {
            this.listeners.remove(listener);
        }
    }

    public void removeQuiet(INode node) {
        this.list.remove(node);
    }

    @Override
    public String toString() {
        return this.payload.getKey();
    }

}
